﻿using System;
using System.Diagnostics;
using System.Windows;

namespace NanoMvvm
{
    public sealed class NanoMvvmFramework
    {
        private static NanoMvvmFramework instance;

        static NanoMvvmFramework()
        {
        }

        private NanoMvvmFramework(Application app)
        {
            Application = app;
            Resources = new ResourceHelper(this);
            Localization = new LocalizationHelper();
            Synchronization = new SynchronizationHelper();
        }

        public static event EventHandler FrameworkInitialized
        {
            add
            {
                if (!IsInitialized)
                {
                    Initalized += value;
                }
            }
            remove
            {
                if (!IsInitialized)
                {
                    Initalized -= value;
                }
            }
        }

        private static event EventHandler Initalized;

        public static NanoMvvmFramework Instance
        {
            get
            {
                if (instance == null && RunModeResolver.InDesignMode)
                {
                    Initialize(Application.Current);
                }

                return instance;
            }

            private set
            {
                instance = value;
            }
        }

        public static bool IsInitialized
        {
            get
            {
                return instance != null;
            }
        }

        public ResourceHelper Resources { get; private set; }

        public SynchronizationHelper Synchronization { get; private set; }

        public LocalizationHelper Localization { get; private set; }

        public Application Application { get; private set; }

        public static void Initialize(Application app)
        {
            if (IsInitialized)
            {
                return;
            }

            if (RunModeResolver.InDesignMode)
            {
                Instance = new NanoMvvmFramework(app);

                return;
            }

            if (app == null)
            {
                throw new ArgumentNullException("app");
            }

            Instance = new NanoMvvmFramework(app);

            app.ShutdownMode = ShutdownMode.OnExplicitShutdown;

            Instance.Resources.LoadLocalXamlLibrary();

            AppDomain.CurrentDomain.UnhandledException += CurrentDomainUnhandledException;

            OnInitialized();
        }

        public void Shutdown()
        {
            Synchronization.Main.Send(state => Application.Shutdown(), null);
        }

        private static void OnInitialized()
        {
            var handler = Initalized;
            if (handler != null)
            {
                handler(Instance, EventArgs.Empty);
            }

            Initalized = null;
        }

        private static void CurrentDomainUnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            // TODO: log
            Trace.WriteLine(ExceptionHelper.GetInnerMostException((Exception)e.ExceptionObject).Message);

            Instance.Application.Shutdown();
        }
    }
}